﻿using mozhi.smarterp.Finance.Enums;
using Mozhi.Abp.Domain.BasicData;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp;

namespace mozhi.smarterp.Finance.Accounts
{
    /// <summary>
    /// 科目
    /// </summary>
    public class Account : AggregateRootBase<Guid>
    {
        /// <summary>
        /// 父级
        /// </summary>
        public Guid? ParentId { private set; get; }

        /// <summary>
        /// 科目类型
        /// </summary>
        public AccountType AccountType { private set; get; }

        /// <summary>
        ///会计准则
        /// </summary>
        public AccountingStandardType AccountStandardType { private set; get; }

        /// <summary>
        /// 代码
        /// </summary>
        public string Code { private set; get; }

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { private set; get; }

        /// <summary>
        /// 全称
        /// </summary>
        public string FullName { private set; get; }

        /// <summary>
        /// 科目方向
        /// </summary>
        public AccountDirectionType Direction { private set; get; }

        /// <summary>
        /// 是否子级科目
        /// </summary>
        public bool IsLeaf { private set; get; }

        /// <summary>
        /// 是否外币核算
        /// </summary>
        public bool IsForeignCurrencyAccounting { private set; get; }

        /// <summary>
        /// 数量核算
        /// </summary>
        public bool IsQuantityAccounting‌ {  private set; get; }

        /// <summary>
        /// 期末调汇
        /// </summary>
        public bool IsExchangeAdjustment {  private set; get; }

        /// <summary>
        /// 核算维度(中间模型具象化，不在使用关系命名)
        /// </summary>
        //public List<AccountDimensionRelation> Dimensions { private set; get; }

        /// <summary>
        /// 核算维度
        /// </summary>
        public List<AccountDimensionItem> DimensionItems { private set; get; }

        private Account(){}

        public Account(Guid id, string code, string name, AccountType accountType, AccountDirectionType directionType)
        {
            this.Id = id;
            this.Code = code;
            this.Name = name;
            this.Direction = directionType;
            this.AccountType = accountType;
            this.Activated = true;

            DimensionItems = new List<AccountDimensionItem>();

            Validate();
        }

        /// <summary>
        /// 设置父级科目
        /// </summary>
        /// <param name="parent"></param>
        public void SetParent(Account parent)
        {
            if (parent == null)
                throw new UserFriendlyException("父级科目不能为空");

            if (ParentId.HasValue && ParentId != parent.Id)
                throw new UserFriendlyException("科目已绑定父级科目，不允许重新绑定");

            this.AccountType = parent.AccountType;
            this.AccountStandardType = parent.AccountStandardType;

            var parentFullNameSplits = parent.FullName.IsNullOrEmpty() ? [parent.Code , parent.Name] : parent.FullName.Split(' ');

            if (parentFullNameSplits.Length != 2)
                throw new BusinessException("100000", "父级科目的全称不符合规则：" + parent.FullName);

            this.ParentId = parent.Id;

            this.Code = GetStandardCode(parent.Code, this.Code);

            this.FullName = $"{Code} {parentFullNameSplits[1]}-{Name}";

            this.AccountStandardType = parent.AccountStandardType;

            this.IsLeaf = true;

            Validate();
        }

        /// <summary>
        /// 设置核算维度
        /// </summary>
        /// <param name="items"></param>
        public void SetDimensionItems(List<AccountDimensionItem> items)
        {
            if (items == null || items.Count == 0)
                return;

            foreach (var item in items)
            {
                var match = DimensionItems.FirstOrDefault(x => x.DimensionId == item.DimensionId);

                if (match == null)
                {
                    item.SetAccountId(Id);
                    DimensionItems.Add(item);
                }
                else
                    match.ChangeStatus(item.Activated, item.IsRequire);
            }

            var itemIds = items.Select(x => x.Id).ToList();

            var removedItems = DimensionItems.Where(x => !itemIds.Contains(x.Id)).ToList();

            foreach (var item in removedItems)
            {
                DimensionItems.Remove(item);
            }
        }

        /// <summary>
        /// 修改状态
        /// </summary>
        /// <param name="activated"></param>
        public void SetStatus(bool activated)
        {
            this.Activated = activated;
        }

        /// <summary>
        /// 修改科目层级
        /// </summary>
        /// <param name="leaf"></param>
        public void SetLevel(bool leaf)
        {
            if (IsLeaf == leaf)
                return;

            IsLeaf = leaf;

            //非子级科目，需要清空核算维度信息
            if (leaf == false)
                DimensionItems.Clear();

        }

        public void SetDirection(AccountDirectionType direction)
        {
            this.Direction = direction;
        }

        public void SetForeignCurrency(bool isForeignCurrency)
        {
            this.IsForeignCurrencyAccounting = isForeignCurrency;
        }

        public void ChangeBaseInfo(string code, string name , string fullName)
        {
            this.Code = code;
            this.Name = name;

            this.FullName = fullName.IsNullOrEmpty()  ? this.FullName : fullName;

            Validate();
        }

        public void SetAccountStandard(AccountingStandardType accountingStandard)
        {
            this.AccountStandardType = accountingStandard;
        }

        /// <summary>
        /// 获取核算维度的hash值
        /// </summary>
        /// <returns></returns>
        public int GetDimensionItemHashCode()
        {
            List<string> items = new List<string>();

            if (DimensionItems == null || DimensionItems.Count == 0)
                return "".GetHashCode();

            foreach (var dimensionItem in DimensionItems)
            {
                items.Add(dimensionItem.DimensionId.ToString() + dimensionItem.IsRequire.ToString().ToLower());
            }

            items = items.OrderBy(x => x).ToList();

            return items.GetHashCode();
        }

        #region
        private void Validate()
        {
            var messages = new List<string>();

            if (this.Direction == default)
                messages.Add("科目方向为必填项");

            if (Code.IsNullOrEmpty())
                messages.Add("科目代码为必填项");

            if (Name.IsNullOrEmpty())
                messages.Add("科目名称为必填项");

            if (AccountType == default)
                messages.Add("科目类型为必填项");

            if (messages.Count > 0)
                throw new UserFriendlyException(string.Join(";", messages), "10001");
        }

        private string GetStandardCode(string parentCode, string code)
        {
            var splitArray = code.Split(".");

            if (splitArray.Length == 1)
                return parentCode + "." + code;

            return parentCode + "." + splitArray[splitArray.Length - 1];
        }
        #endregion
    }

    public class AccountDimensionItem : EntityBase<Guid>
    {
        /// <summary>
        ///科目Id
        /// </summary>
        public Guid AccountId { private set; get; }

        /// <summary>
        /// 核算维度Id
        /// </summary>
        public Guid DimensionId { private set; get; }

        /// <summary>
        /// 核算维度名称
        /// </summary>
        public string DimensionName { private set; get; }

        /// <summary>
        /// 是否必录
        /// </summary>
        public bool IsRequire { set; get; }

        private AccountDimensionItem() { }

        public AccountDimensionItem(Guid accountId, Guid dimensionId , bool isRequire , string dimensionName , bool activated)
        {
            AccountId = accountId;
            DimensionId = dimensionId;
            IsRequire = isRequire;
            DimensionName = dimensionName;
            Activated = activated;

            Validate();
        }

        
        public void SetAccountId(Guid accountId)
        {
            AccountId = accountId;
        }

        public void ChangeStatus(bool activated , bool isRequire)
        {
            Activated = activated;
            IsRequire = isRequire;
        }

        private void Validate()
        {
            if (AccountId == default)
                throw new UserFriendlyException("科目不能为空", "100000");

            if (DimensionId == default)
                throw new UserFriendlyException("核算维度值不能为空", "100000");
        }
    }
}
